<!doctype html>
<html lang="zh-CN">
<head>
	<meta charset="utf-8">
	<title>Laravel - 为 WEB 艺术家创造的 PHP 框架。 | Laravel 中文网</title>
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
	<meta name="author" content="Laravel 中文网">
	<meta name="description" content="Laravel - 为 WEB 艺术家创造的 PHP 框架。| Laravel 中文网">
	<meta name="keywords" content="Laravel中文社区,php框架,laravel中文网,php framework,restful routing,laravel,laravel php">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<!--[if lte IE 9]>
		<script src="http://cdn.bootcss.com/html5shiv/3.7.2/html5shiv.min.js"></script>
	<![endif]-->
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="stylesheet" href="../../assets/css/laravel.css">
</head>
<body class="docs language-php">

	<span class="overlay"></span>

	<nav class="main">
		<div class="container">
			<a href="../../index.html" class="brand">
				<img src="../../assets/img/laravel-logo.png" height="30">
				Laravel
			</a>

			<div class="responsive-sidebar-nav">
				<a href="#" class="toggle-slide menu-link btn">&#9776;</a>
			</div>

				<div class="switcher">
					<div class="dropdown">
						<button class="btn dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-expanded="true">
							<!--<span class="faint">v</span> -->
							4.1
							<span class="caret"></span>
						</button>
						<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
								<li role="presentation">
									<a role="menuitem" tabindex="-1" href="../5.0/index.html">5.0</a>
								</li>
								<li role="presentation">
									<a role="menuitem" tabindex="-1" href="../4.2/index.html">4.2</a>
								</li>
								<li role="presentation">
									<a role="menuitem" tabindex="-1" href="index.html">4.1</a>
								</li>
								<li role="presentation">
									<a role="menuitem" tabindex="-1" href="../4.0/index.html">4.0</a>
								</li>
						</ul>
					</div>
				</div>

			<ul class="main-nav">
				<li class="nav-docs"><a href="../index.html">中文文档</a></li>
				<li class="nav-community"><a href="http://wenda.golaravel.com" target="_blank">问答社区</a></li>
				<li class="nav-api"><a href="http://laravel.com/api/5.0/" target="_blank">API</a></li>
				<li class="nav-laracasts"><a href="https://laracasts.com" target="_blank">视频教程（国外）</a></li>
				<li class="nav-forge"><a href="https://forge.laravel.com" target="_blank">Forge</a></li>
				
			</ul>
		</div>
	</nav>

		<nav id="slide-menu" class="slide-menu" role="navigation">
		
		<div class="brand">
			<a href="../../index.html">
				<img src="../../assets/img/laravel-logo-white.png" height="50">
			</a>
		</div>

		<ul class="slide-main-nav">
			<li><a href="../../index.html">首页</a></li>
			<li class="nav-docs"><a href="../index.html">中文文档</a></li>
			<li class="nav-community"><a href="http://wenda.golaravel.com" target="_blank">问答社区</a></li>
			<li class="nav-api"><a href="http://laravel.com/api/5.0/" target="_blank">API</a></li>
			<li class="nav-laracasts"><a href="https://laracasts.com" target="_blank">视频教程（国外）</a></li>
			<li class="nav-forge"><a href="https://forge.laravel.com" target="_blank">Forge</a></li>
			
		</ul>

		<div class="slide-docs-nav">
			<h2>文档目录</h2>
			<ul>
<li>序言
<ul>
<li><a href="introduction.html">简介</a></li>
<li><a href="quick.html">快速入门</a></li>
<li><a href="releases.html">Release Notes</a></li>
<li><a href="upgrade.html">Upgrade Guide</a></li>
</ul>
</li>
<li>开始学习
<ul>
<li><a href="installation.html">安装</a></li>
<li><a href="configuration.html">配置</a></li>
<li><a href="lifecycle.html">Request的生命周期</a></li>
<li><a href="routing.html">路由</a></li>
<li><a href="requests.html">请求与输入</a></li>
<li><a href="responses.html">视图 &amp; Response</a></li>
<li><a href="controllers.html">控制器</a></li>
<li><a href="errors.html">错误 &amp; 日志</a></li>
</ul>
</li>
<li>深度历险
<ul>
<li><a href="security.html">Authentication</a></li>
<li><a href="cache.html">缓存</a></li>
<li><a href="extending.html">核心扩展</a></li>
<li><a href="events.html">事件</a></li>
<li><a href="facades.html">Facades</a></li>
<li><a href="html.html">表单 &amp; HTML</a></li>
<li><a href="helpers.html">有用的工具函数</a></li>
<li><a href="ioc.html">IoC 容器</a></li>
<li><a href="localization.html">本地化</a></li>
<li><a href="mail.html">邮件</a></li>
<li><a href="packages.html">扩展包开发</a></li>
<li><a href="pagination.html">分页</a></li>
<li><a href="queues.html">队列</a></li>
<li><a href="security.html">安全</a></li>
<li><a href="session.html">Session</a></li>
<li><a href="ssh.html">SSH</a></li>
<li><a href="templates.html">模板</a></li>
<li><a href="testing.html">单元测试</a></li>
<li><a href="validation.html">验证</a></li>
</ul>
</li>
<li>数据库
<ul>
<li><a href="database.html">基本用法</a></li>
<li><a href="queries.html">查询构造器</a></li>
<li><a href="eloquent.html">Eloquent ORM</a></li>
<li><a href="schema.html">结构生成器</a></li>
<li><a href="migrations.html">迁移 &amp; 数据填充</a></li>
<li><a href="redis.html">Redis</a></li>
</ul>
</li>
<li>Artisan 命令行工具
<ul>
<li><a href="artisan.html">概览</a></li>
<li><a href="commands.html">Artisan 开发</a></li>
</ul>
</li>
<li>贡献者
<ul>
<li><a href="contributors.html">中文翻译贡献者名单</a></li>
</ul>
</li>
</ul>

		</div>

	</nav>

	<div class="docs-wrapper container">

		<section class="sidebar">
			<ul>
<li>序言
<ul>
<li><a href="introduction.html">简介</a></li>
<li><a href="quick.html">快速入门</a></li>
<li><a href="releases.html">Release Notes</a></li>
<li><a href="upgrade.html">Upgrade Guide</a></li>
</ul>
</li>
<li>开始学习
<ul>
<li><a href="installation.html">安装</a></li>
<li><a href="configuration.html">配置</a></li>
<li><a href="lifecycle.html">Request的生命周期</a></li>
<li><a href="routing.html">路由</a></li>
<li><a href="requests.html">请求与输入</a></li>
<li><a href="responses.html">视图 &amp; Response</a></li>
<li><a href="controllers.html">控制器</a></li>
<li><a href="errors.html">错误 &amp; 日志</a></li>
</ul>
</li>
<li>深度历险
<ul>
<li><a href="security.html">Authentication</a></li>
<li><a href="cache.html">缓存</a></li>
<li><a href="extending.html">核心扩展</a></li>
<li><a href="events.html">事件</a></li>
<li><a href="facades.html">Facades</a></li>
<li><a href="html.html">表单 &amp; HTML</a></li>
<li><a href="helpers.html">有用的工具函数</a></li>
<li><a href="ioc.html">IoC 容器</a></li>
<li><a href="localization.html">本地化</a></li>
<li><a href="mail.html">邮件</a></li>
<li><a href="packages.html">扩展包开发</a></li>
<li><a href="pagination.html">分页</a></li>
<li><a href="queues.html">队列</a></li>
<li><a href="security.html">安全</a></li>
<li><a href="session.html">Session</a></li>
<li><a href="ssh.html">SSH</a></li>
<li><a href="templates.html">模板</a></li>
<li><a href="testing.html">单元测试</a></li>
<li><a href="validation.html">验证</a></li>
</ul>
</li>
<li>数据库
<ul>
<li><a href="database.html">基本用法</a></li>
<li><a href="queries.html">查询构造器</a></li>
<li><a href="eloquent.html">Eloquent ORM</a></li>
<li><a href="schema.html">结构生成器</a></li>
<li><a href="migrations.html">迁移 &amp; 数据填充</a></li>
<li><a href="redis.html">Redis</a></li>
</ul>
</li>
<li>Artisan 命令行工具
<ul>
<li><a href="artisan.html">概览</a></li>
<li><a href="commands.html">Artisan 开发</a></li>
</ul>
</li>
<li>贡献者
<ul>
<li><a href="contributors.html">中文翻译贡献者名单</a></li>
</ul>
</li>
</ul>

		</section>

		<article>
			<h1>Eloquent ORM</h1>
<ul>
<li><a href="#introduction">简介</a></li>
<li><a href="#basic-usage">基本用法</a></li>
<li><a href="#mass-assignment">集体赋值</a></li>
<li><a href="#insert-update-delete">插入、更新、删除</a></li>
<li><a href="#soft-deleting">软删除</a></li>
<li><a href="#timestamps">时间戳</a></li>
<li><a href="#query-scopes">查询范围</a></li>
<li><a href="#relationships">关系</a></li>
<li><a href="#querying-relations">查询关系</a></li>
<li><a href="#eager-loading">预先加载</a></li>
<li><a href="#inserting-related-models">插入相关模型</a></li>
<li><a href="#touching-parent-timestamps">触发父模型时间戳</a></li>
<li><a href="#working-with-pivot-tables">与数据透视表工作</a></li>
<li><a href="#collections">集合</a></li>
<li><a href="#accessors-and-mutators">访问器和调整器</a></li>
<li><a href="#date-mutators">日期调整器</a></li>
<li><a href="#model-events">模型事件</a></li>
<li><a href="#model-observers">模型观察者</a></li>
<li><a href="#converting-to-arrays-or-json">转为数组或JSON</a></li>
</ul>
<p><a name="introduction"></a></p>
<h2>简介</h2>
<p>Laravel 自带的 Eloquent ORM 为您的数据库提供了一个优雅的、简单的 ActiveRecord 实现。每一个数据库的表有一个对应的 &quot;Model&quot; 用来与这张表交互。</p>
<p>在开始之前，确认已在 <code>app/config/database.php</code> 文件中配置好数据库连接。</p>
<p><a name="basic-usage"></a></p>
<h2>基本用法</h2>
<p>首先，创建一个 Eloquent 模型。模型通常在 <code>app/models</code> 目录，但是您可以自由地把它们放在任何地方，只要它能根据您的 <code>composer.json</code> 文件自动加载。</p>
<p><strong>定义一个 Eloquent 模型</strong></p>
<pre><code>class User extends Eloquent {}
</code></pre>
<p>注意我们并没有告诉 Eloquent 我们为 <code>User</code> 模型使用了哪一张表。类名的小写、复数的形式将作为表名，除非它被显式地指定。所以，在这种情况下，Eloquent 将假设 <code>User</code> 模型在 <code>users</code> 表中保存记录。您可以在模型中定义一个 <code>table</code> 属性来指定一个自定义的表名：</p>
<pre><code>class User extends Eloquent {

    protected $table = 'my_users';

}
</code></pre>
<blockquote>
<p><strong>注意:</strong> Eloquent 将假设每张表有一个名为 <code>id</code> 的主键。您可以定义 <code>primaryKey</code> 属性来覆盖这个约定。同样，您可以定义一个 <code>connection</code> 属性来覆盖在使用这个模型时所用的数据库连接。</p>
</blockquote>
<p>一旦模型被定义，您可以开始在表中检索和创建记录。注意在默认情况下您将需要在表中定义 <code>updated_at</code> 和 <code>created_at</code> 字段。如果您不希望这些列被自动维护，在模型中设置 <code>$timestamps</code> 属性为 <code>false</code>。</p>
<p><strong>获取所有记录</strong></p>
<pre><code>$users = User::all();
</code></pre>
<p><strong>根据主键获取一条记录</strong></p>
<pre><code>$user = User::find(1);

var_dump($user-&gt;name);
</code></pre>
<blockquote>
<p><strong>注意:</strong> 所有在 [查询构建器] 中适用的函数在 Eloquent 模型的查询中同样适用。</p>
</blockquote>
<p><strong>根据主键获取一条记录或者抛出一个异常</strong></p>
<p>有时您可能希望当记录没有被找到时抛出一个异常，允许您使用 <code>App::error</code> 处理器捕捉这些异常并显示404页面。</p>
<pre><code>$model = User::findOrFail(1);

$model = User::where('votes', '&gt;', 100)-&gt;firstOrFail();
</code></pre>
<p>注册错误处理器，请监听 <code>ModelNotFoundException</code>：</p>
<pre><code>use Illuminate\Database\Eloquent\ModelNotFoundException;

App::error(function(ModelNotFoundException $e)
{
    return Response::make('Not Found', 404);
});
</code></pre>
<p><strong>使用 Eloquent 模型查询</strong></p>
<pre><code>$users = User::where('votes', '&gt;', 100)-&gt;take(10)-&gt;get();

foreach ($users as $user)
{
    var_dump($user-&gt;name);
}
</code></pre>
<p>当然，您也可以使用查询构建器的统计函数。</p>
<p><strong>Eloquent 统计</strong></p>
<pre><code>$count = User::where('votes', '&gt;', 100)-&gt;count();
</code></pre>
<p>如果您无法通过通过连贯的接口产生查询，可以使用 <code>whereRaw</code>：</p>
<pre><code>$users = User::whereRaw('age &gt; ? and votes = 100', array(25))-&gt;get();
</code></pre>
<p><strong>Chunking Results</strong></p>
<p>If you need to process a lot (thousands) of Eloquent records, using the <code>chunk</code> command will allow you to do without eating all of your RAM:</p>
<pre><code>User::chunk(200, function($users)
{
    foreach ($users as $user)
    {
        //
    }
});
</code></pre>
<p>The first argument passed to the method is the number of records you wish to receive per &quot;chunk&quot;. The Closure passed as the second argument will be called for each chunk that is pulled from the database.</p>
<p><strong>指定查询的数据库连接</strong></p>
<p>您可能需要在运行一个 Eloquent 查询的时候指定数据库连接，只需要使用 <code>on</code> 函数：</p>
<pre><code>$user = User::on('connection-name')-&gt;find(1);
</code></pre>
<p><a name="mass-assignment"></a></p>
<h2>集体赋值</h2>
<p>当创建一个新的模型，您可以传递属性的数组到模型的构造函数。这些属性将通过集体赋值分配给模型。这是很方便的，但把用户的输入盲目地传给模型可能是一个<strong>严重的</strong>安全问题。如果把用户输入盲目地传递给模型，用户可以自由地修改<strong>任何</strong>或者<strong>全部</strong>模型的属性。基于这个原因，默认情况下所有 Eloquent 模型将防止集体赋值。</p>
<p>首先，在模型中设置 <code>fillable</code> 或 <code>guarded</code> 属性。</p>
<p><code>fillable</code> 属性指定哪些属性可以被集体赋值。这可以在类或接口层设置。</p>
<p><strong>在模型中定义 Fillable 属性</strong></p>
<pre><code>class User extends Eloquent {

    protected $fillable = array('first_name', 'last_name', 'email');

}
</code></pre>
<p>在这个例子中，只有三个被列出的属性可以被集体赋值。</p>
<p><code>fillable</code> 的反义词是 <code>guarded</code>，将做为一个黑名单而不是白名单：</p>
<p><strong>在模型中定义 Guarded 属性</strong></p>
<pre><code>class User extends Eloquent {

    protected $guarded = array('id', 'password');

}
</code></pre>
<p>在这个例子中，<code>id</code> 和 <code>password</code> 属性将<strong>不</strong>被允许集体赋值。所有其他属性将被允许集体赋值。您可以使用 guard 方法阻止<strong>所有</strong>属性被集体赋值：</p>
<p><strong>阻止所有属性集体赋值</strong></p>
<pre><code>protected $guarded = array('*');
</code></pre>
<p><a name="insert-update-delete"></a></p>
<h2>插入、更新、删除</h2>
<p>为了从模型中向数据库中创建一个新的记录，简单地创建一个模型实例并调用 <code>save</code> 函数。</p>
<p><strong>保存一个新的模型</strong></p>
<pre><code>$user = new User;

$user-&gt;name = 'John';

$user-&gt;save();
</code></pre>
<blockquote>
<p><strong>注意:</strong> 通常您的 Eloquent 模型将有自动递增的键。然而，如果您希望指定您自定义的键，在模型中设置 <code>incrementing</code> 属性为 <code>false</code>。</p>
</blockquote>
<p>您也可以使用 <code>create</code> 函数在一行代码中保存一个新的模型。被插入的模型实例将从函数中返回。但是，在您这样做之前，您需要在模型中指定 <code>fillable</code> 或者 <code>guarded</code> 属性，因为所有 Eloquent 模型默认阻止集体赋值。</p>
<p>在保存或创建一个使用自增ID的新模型之后，可以通过对象的 <code>id</code> 属性获取此自增ID：</p>
<pre><code>$insertedId = $user-&gt;id;
</code></pre>
<p><strong>在模型中设置 Guarded 属性</strong></p>
<pre><code>class User extends Eloquent {

    protected $guarded = array('id', 'account_id');

}
</code></pre>
<p><strong>使用模型的 Create 函数</strong></p>
<pre><code>// Create a new user in the database...
$user = User::create(array('name' =&gt; 'John'));

// Retrieve the user by the attributes, or create it if it doesn't exist...
$user = User::firstOrCreate(array('name' =&gt; 'John'));

// Retrieve the user by the attributes, or instantiate a new instance...
$user = User::firstOrNew(array('name' =&gt; 'John'));
</code></pre>
<p>为了更新一个模型，您可以检索它，改变一个属性，然后使用 <code>save</code> 函数：</p>
<p><strong>更新一个检索到的模型</strong></p>
<pre><code>$user = User::find(1);

$user-&gt;email = 'john@foo.com';

$user-&gt;save();
</code></pre>
<p>有时您可能希望不仅保存模型，还有它的所有关系。为此，您可以使用 <code>push</code> 函数：</p>
<p><strong>保存一个模型和关系</strong></p>
<pre><code>$user-&gt;push();
</code></pre>
<p>您也可以在一组模型上运行更新：</p>
<pre><code>$affectedRows = User::where('votes', '&gt;', 100)-&gt;update(array('status' =&gt; 2));
</code></pre>
<p>删除一个模型，在实例中调用 <code>delete</code> 函数：</p>
<p><strong>删除一个存在的模型</strong></p>
<pre><code>$user = User::find(1);

$user-&gt;delete();
</code></pre>
<p><strong>根据主键删除一个模型</strong></p>
<pre><code>User::destroy(1);

User::destroy(array(1, 2, 3));

User::destroy(1, 2, 3);
</code></pre>
<p>当然，您可以在一组模型中运行删除查询：</p>
<pre><code>$affectedRows = User::where('votes', '&gt;', 100)-&gt;delete();
</code></pre>
<p>如果您希望简单的在一个模型中更新时间戳，可以使用 <code>touch</code> 函数：</p>
<p><strong>只更新模型的时间戳</strong></p>
<pre><code>$user-&gt;touch();
</code></pre>
<p><a name="soft-deleting"></a></p>
<h2>软删除</h2>
<p>当软删除一个模型，它并没有真的从数据库中删除。相反，一个 <code>deleted_at</code> 时间戳在记录中被设置。为一个模型开启软删除，在模型中指定 <code>softDelete</code> 属性：</p>
<pre><code>class User extends Eloquent {

    protected $softDelete = true;

}
</code></pre>
<p>为了在您的表中添加一个 <code>deleted_at</code> 字段，您可以在迁移中使用 <code>softDeletes</code> 函数：</p>
<pre><code>$table-&gt;softDeletes();
</code></pre>
<p>现在，当您在一个模型中调用 <code>delete</code> 函数，<code>deleted_at</code> 字段将被设置为当前的时间戳。在使用软删除的模型中查询，被软删除的模型将不被包含进查询结果中。为了强制已删除的模型出现在结果集中，在查询中使用 <code>withTrashed</code> 函数：</p>
<p><strong>强制软删除的模型到结果集中</strong></p>
<pre><code>$users = User::withTrashed()-&gt;where('account_id', 1)-&gt;get();
</code></pre>
<p>如果您希望在结果集中<strong>只</strong>包含软删除的模型，您可以使用 <code>onlyTrashed</code> 函数：</p>
<pre><code>$users = User::onlyTrashed()-&gt;where('account_id', 1)-&gt;get();
</code></pre>
<p>恢复一个已被软删除的记录，使用 <code>restore</code> 函数：</p>
<pre><code>$user-&gt;restore();
</code></pre>
<p>您也可以在查询中使用 <code>restore</code> 函数：</p>
<pre><code>User::withTrashed()-&gt;where('account_id', 1)-&gt;restore();
</code></pre>
<p><code>restore</code>  函数也可以在关系中被使用：</p>
<pre><code>$user-&gt;posts()-&gt;restore();
</code></pre>
<p>如果您希望从数据库中真正删除一个模型，您可以使用 <code>forceDelete</code> 函数：</p>
<pre><code>$user-&gt;forceDelete();
</code></pre>
<p><code>forceDelete</code> 函数也可以在关系中被使用：</p>
<pre><code>$user-&gt;posts()-&gt;forceDelete();
</code></pre>
<p>检测一个给定的模型实例是否被软删除，可以使用 <code>trashed</code> 函数：</p>
<pre><code>if ($user-&gt;trashed())
{
    //
}
</code></pre>
<p><a name="timestamps"></a></p>
<h2>时间戳</h2>
<p>默认情况下，Eloquent 在数据的表中自动地将维护 <code>created_at</code> 和 <code>updated_at</code> 字段。只需简单的添加这些 <code>timestamp</code> 字段到表中，Eloquent 将为您做剩余的工作。如果您不希望 Eloquent 维护这些字段，在模型中添加以下属性：</p>
<p><strong>禁止自动时间戳</strong></p>
<pre><code>class User extends Eloquent {

    protected $table = 'users';

    public $timestamps = false;

}
</code></pre>
<p>如果您希望定制时间戳的格式，可以在模型中重写 <code>getDateFormat</code> 函数：</p>
<p><strong>提供一个定制的时间戳格式</strong></p>
<pre><code>class User extends Eloquent {

    protected function getDateFormat()
    {
        return 'U';
    }

}
</code></pre>
<p><a name="query-scopes"></a></p>
<h2>查询范围</h2>
<p>范围允许您容易在模型中重用查询逻辑。定义一个范围，简单的用 <code>scope</code> 为模型添加前缀：</p>
<p><strong>定义一个查询范围</strong></p>
<pre><code>class User extends Eloquent {

    public function scopePopular($query)
    {
        return $query-&gt;where('votes', '&gt;', 100);
    }

    public function scopeWomen($query)
    {
        return $query-&gt;whereGender('W');
    }

}
</code></pre>
<p><strong>使用一个查询范围</strong></p>
<pre><code>$users = User::popular()-&gt;women()-&gt;orderBy('created_at')-&gt;get();
</code></pre>
<p><strong>动态范围</strong></p>
<p>有时您可能希望定义一个接受参数的范围。只需要添加您的参数到您的范围函数：</p>
<pre><code>class User extends Eloquent {

    public function scopeOfType($query, $type)
    {
        return $query-&gt;whereType($type);
    }

}
</code></pre>
<p>然后在范围函数调用中传递参数：</p>
<pre><code>$users = User::ofType('member')-&gt;get();
</code></pre>
<p><a name="relationships"></a></p>
<h2>关系</h2>
<p>当然，您的数据库可能是彼此相关的。比如，一篇博客文章可能有许多评论，或者一个订单与下订单的用户相关。Eloquent 使得管理和处理这些关系变得简单。Laravel 提供了四种类型的关系：</p>
<ul>
<li><a href="#one-to-one">一对一</a></li>
<li><a href="#one-to-many">一对多</a></li>
<li><a href="#many-to-many">多对多</a></li>
<li><a href="#has-many-through">Has Many Through</a></li>
<li><a href="#polymorphic-relations">多态关系</a></li>
</ul>
<p><a name="one-to-one"></a></p>
<h3>一对一</h3>
<p>一个一对一关系是一种非常基础的关系。比如，一个 <code>User</code> 模型可以有一个 Phone`。我们可以在 Eloquent 中定义这个关系：</p>
<p><strong>定义一个一对一关系</strong></p>
<pre><code>class User extends Eloquent {

    public function phone()
    {
        return $this-&gt;hasOne('Phone');
    }

}
</code></pre>
<p>传递给 <code>hasOne</code> 函数的第一个参数是相关模型的名字。一旦这个关系被定义，我们可以使用 Eloquent 的 [动态属性] 获取它：</p>
<pre><code>$phone = User::find(1)-&gt;phone;
</code></pre>
<p>这条语句所产生的 SQL 语句如下:</p>
<pre><code>select * from users where id = 1

select * from phones where user_id = 1
</code></pre>
<p>注意 Eloquent 假设关系的外键基于模型的名字。在这个例子中假设 <code>Phone</code> 模型使用一个 <code>user_id</code> 外键。如果您希望覆盖这个惯例，您可以为传递 <code>hasOne</code> 函数传递第二个参数。Furthermore, you may pass a third argument to the method to specify which local column that should be used for the association:</p>
<pre><code>return $this-&gt;hasOne('Phone', 'foreign_key');

return $this-&gt;hasOne('Phone', 'foreign_key', 'local_key');
</code></pre>
<p>在 <code>Phone</code> 模型定义逆向关系，我们使用 <code>belongsTo</code> 函数：</p>
<p><strong>定义一个逆向关系</strong></p>
<pre><code>class Phone extends Eloquent {

    public function user()
    {
        return $this-&gt;belongsTo('User');
    }

}
</code></pre>
<p>在上面的例子中，Eloquent 将在 <code>phones</code> 表中寻找 <code>user_id</code> 字段。如果您想定义一个不同的外键字段，您可以通过 <code>belongsTo</code> 函数的第二个参数传递它：</p>
<pre><code>class Phone extends Eloquent {

    public function user()
    {
        return $this-&gt;belongsTo('User', 'local_key');
    }

}
</code></pre>
<p>Additionally, you pass a third parameter which specifies the name of the associated column on the parent table:</p>
<pre><code>class Phone extends Eloquent {

    public function user()
    {
        return $this-&gt;belongsTo('User', 'local_key', 'parent_key');
    }

}
</code></pre>
<p><a name="one-to-many"></a></p>
<h3>一对多</h3>
<p>一个一对多关系的例子是一篇博客文章有许多评论。我们可以像这样定义关系模型：</p>
<pre><code>class Post extends Eloquent {

    public function comments()
    {
        return $this-&gt;hasMany('Comment');
    }

}
</code></pre>
<p>现在我们可以通过 <a href="#dynamic-properties">动态属性</a> 访问文章的评论：</p>
<pre><code>$comments = Post::find(1)-&gt;comments;
</code></pre>
<p>如果您需要添加进一步的约束检索哪些评论，我们可以调用 <code>comments</code> 函数连接链式条件：</p>
<pre><code>$comments = Post::find(1)-&gt;comments()-&gt;where('title', '=', 'foo')-&gt;first();
</code></pre>
<p>再次，如果您想覆盖默认的外键，可以给 <code>hasMany</code> 函数传递第二个参数。And, like the <code>hasOne</code> relation, the local column may also be specified:</p>
<pre><code>return $this-&gt;hasMany('Comment', 'foreign_key');

return $this-&gt;hasMany('Comment', 'foreign_key', 'local_key');
</code></pre>
<p>在 <code>Comment</code> 模型中定义逆向关系，我们使用 <code>belongsTo</code> 函数：</p>
<p><strong>定义逆向关系</strong></p>
<pre><code>class Comment extends Eloquent {

    public function post()
    {
        return $this-&gt;belongsTo('Post');
    }

}
</code></pre>
<p><a name="many-to-many"></a></p>
<h3>多对多</h3>
<p>多对多关系更复杂的关系类型。这种关系的一个例子是一个用户和角色，这个角色也可被其他用户共享。比如，许多用户有 &quot;Admin&quot; 的角色。这个关系需要三个表：<code>users</code>, <code>roles</code> 以及 <code>role_user</code>。<code>role_user</code> 表来源于相关的角色名，并且有 <code>user_id</code> 和 <code>role_id</code> 字段。</p>
<p>我们可以使用 <code>belongsToMany</code> 函数定义一个多对多关系：</p>
<pre><code>class User extends Eloquent {

    public function roles()
    {
        return $this-&gt;belongsToMany('Role');
    }

}
</code></pre>
<p>现在，我们可以通过 <code>User</code> 模型获取角色：</p>
<pre><code>$roles = User::find(1)-&gt;roles;
</code></pre>
<p>如果您想使用一个非常规的表名作为关系表，您可以传递它作为第二个参数给 <code>belongsToMany</code> 函数：</p>
<pre><code>return $this-&gt;belongsToMany('Role', 'user_roles');
</code></pre>
<p>您也可以覆盖相关的键：</p>
<pre><code>return $this-&gt;belongsToMany('Role', 'user_roles', 'user_id', 'foo_id');
</code></pre>
<p>当然，您也可以定义在 <code>Role</code> 模型中定义逆向关系：</p>
<pre><code>class Role extends Eloquent {

    public function users()
    {
        return $this-&gt;belongsToMany('User');
    }

}
</code></pre>
<p><a name="has-many-through"></a></p>
<h3>Has Many Through</h3>
<p>The &quot;has many through&quot; relation provides a convenient short-cut for accessing distant relations via an intermediate relation. For example, a <code>Country</code> model might have many <code>Posts</code> through a <code>Users</code> model. The tables for this relationship would look like this:</p>
<pre><code>countries
    id - integer
    name - string

users
    id - integer
    country_id - integer
    name - string

posts
    id - integer
    user_id - integer
    title - string
</code></pre>
<p>Even though the <code>posts</code> table does not contain a <code>country_id</code> column, the <code>hasManyThrough</code> relation will allow us to access a country's posts via <code>$country-&gt;posts</code>. Let's define the relationship:</p>
<pre><code>class Country extends Eloquent {

    public function posts()
    {
        return $this-&gt;hasManyThrough('Post', 'User');
    }

}
</code></pre>
<p>If you would like to manually specify the keys of the relationship, you may pass them as the third and fourth arguments to the method:</p>
<pre><code>class Country extends Eloquent {

    public function posts()
    {
        return $this-&gt;hasManyThrough('Post', 'User', 'country_id', 'user_id');
    }

}
</code></pre>
<p><a name="polymorphic-relations"></a></p>
<h3>多态关系</h3>
<p>多态关系允许在一个关联中一个模型属于多于一个的其他模型。比如，您可能有一个 photo 模型属于一个员工模型或者一个订单模型。我们可以定义像这样定义这个关系：</p>
<pre><code>class Photo extends Eloquent {

    public function imageable()
    {
        return $this-&gt;morphTo();
    }

}

class Staff extends Eloquent {

    public function photos()
    {
        return $this-&gt;morphMany('Photo', 'imageable');
    }

}

class Order extends Eloquent {

    public function photos()
    {
        return $this-&gt;morphMany('Photo', 'imageable');
    }

}
</code></pre>
<p>现在，我们可以为一个员工或者一个订单获取照片：</p>
<p><strong>获取一个多态关系</strong></p>
<pre><code>$staff = Staff::find(1);

foreach ($staff-&gt;photos as $photo)
{
    //
}
</code></pre>
<p>然而，&quot;polymorphic&quot; 的真正魔力是当您从 <code>Photo</code> 模型中访问员工或者订单的时候：</p>
<p><strong>获取多态关系的属主</strong></p>
<pre><code>$photo = Photo::find(1);

$imageable = $photo-&gt;imageable;
</code></pre>
<p><code>Photo</code> 模型的 <code>imageable</code> 关系将返回一个 <code>Staff</code> 或者 <code>Order</code> 实例，依赖于那种类型的模型拥有这个照片。</p>
<p>帮助理解这是怎样工作的，让我们探讨一个多态关系的数据库结构：</p>
<p><strong>多态关系的数据库结构</strong></p>
<pre><code>staff
    id - integer
    name - string

orders
    id - integer
    price - integer

photos
    id - integer
    path - string
    imageable_id - integer
    imageable_type - string
</code></pre>
<p>这里需要注意的键字段是表 <code>photos</code> 的 <code>imageable_id</code> 和 <code>imageable_type</code> 字段。ID 将包含所属员工或订单的 ID，类型将包含所属模型的类名。当访问 <code>imageable</code> 关系的时候将允许 ORM 检测所属模型的类型。</p>
<p><a name="querying-relations"></a></p>
<h2>查询关系</h2>
<p>当为一个模型获取记录的时候，您可能希望基于一个已存在的关系限制结果集的数目。比如，您希望获取至少有一条评论的文章。为此，您可以使用 <code>has</code> 函数：</p>
<p><strong>Querying Relations When Selecting</strong></p>
<pre><code>$posts = Post::has('comments')-&gt;get();
</code></pre>
<p>您也可以指定一个操作符和数量：</p>
<pre><code>$posts = Post::has('comments', '&gt;=', 3)-&gt;get();
</code></pre>
<p>If you need even more power, you may use the <code>whereHas</code> and <code>orWhereHas</code> methods to put &quot;where&quot; conditions on your <code>has</code> queries:</p>
<pre><code>$posts = Post::whereHas('comments', function($q)
{
    $q-&gt;where('content', 'like', 'foo%');

})-&gt;get();
</code></pre>
<p><a name="dynamic-properties"></a></p>
<h3>动态属性</h3>
<p>Eloquent 允许您通过动态属性访问关系。Eloquent 将为您自动加载关系，并且足够聪明到知道是否调用 <code>get</code> （为一对多关系）或者 <code>first</code> （为一对一关系）。然后，它将通过动态属性访问作为关系。比如，使用下面的 <code>Phone</code> 模型：</p>
<pre><code>class Phone extends Eloquent {

    public function user()
    {
        return $this-&gt;belongsTo('User');
    }

}

$phone = Phone::find(1);
</code></pre>
<p>不需要像这样打印用户的电子邮件：</p>
<pre><code>echo $phone-&gt;user()-&gt;first()-&gt;email;
</code></pre>
<p>它可以简化为：</p>
<pre><code>echo $phone-&gt;user-&gt;email;
</code></pre>
<blockquote>
<p><strong>注意：</strong> 返回多个结果的关系，其本质是返回了 <code>Illuminate\Database\Eloquent\Collection</code> 类的一个实例。</p>
</blockquote>
<p><a name="eager-loading"></a></p>
<h2>预先加载</h2>
<p>预先加载的存在是为了缓解 N + 1 查询问题。比如，考虑一个 <code>Author</code> 相关的 <code>Book</code> 模型。关系定义是这样的：</p>
<pre><code>class Book extends Eloquent {

    public function author()
    {
        return $this-&gt;belongsTo('Author');
    }

}
</code></pre>
<p>现在，考虑下面的代码：</p>
<pre><code>foreach (Book::all() as $book)
{
    echo $book-&gt;author-&gt;name;
}
</code></pre>
<p>此循环将执行一个查询获取表中的所有书籍，然后另一个查询为每本书获取作者。所以，如果我们有 25 本书，这个循环将允许 26 个查询。</p>
<p>值得庆幸的是，我们可以使用预先加载来减少查询的数量。这个关系应该被预先加载通过 <code>with</code> 函数指定：</p>
<pre><code>foreach (Book::with('author')-&gt;get() as $book)
{
    echo $book-&gt;author-&gt;name;
}
</code></pre>
<p>在上面的循环中，只有两个查询被执行：</p>
<pre><code>select * from books

select * from authors where id in (1, 2, 3, 4, 5, ...)
</code></pre>
<p>明智的使用预先加载可以大大提高应用程序的性能。</p>
<p>当然，您可以一次性预先加载多个关系：</p>
<pre><code>$books = Book::with('author', 'publisher')-&gt;get();
</code></pre>
<p>您甚至可以预先加载嵌套关系：</p>
<pre><code>$books = Book::with('author.contacts')-&gt;get();
</code></pre>
<p>在上面的例子中，<code>author</code> 关系将被预先加载，而且作者的 <code>contacts</code> 关系也将被加载。</p>
<h3>预先加载约束</h3>
<p>有时您可能希望预先加载一个关系，但也为预先加载指定一个条件。这里是一个例子：</p>
<pre><code>$users = User::with(array('posts' =&gt; function($query)
{
    $query-&gt;where('title', 'like', '%first%');
}))-&gt;get();
</code></pre>
<p>在这个例子中，我们预先加载用户的文章，但只限于文章的 title 字段中包含单词 &quot;first&quot; 的文章:</p>
<h3>延迟预先加载</h3>
<p>从一个已存在的模型中直接预先加载相关的模型也是可能的。这在动态的决定是否加载相关模型或与缓存结合时可能有用。</p>
<pre><code>$books = Book::all();

$books-&gt;load('author', 'publisher');
</code></pre>
<p><a name="inserting-related-models"></a></p>
<h2>插入相关模型</h2>
<p>您会经常需要插入新的相关模型。比如，你可能希望为一篇文章插入一条新的评论。不需要在模型中手动设置 <code>post_id</code> 外键，您可以直接从它的父模型 <code>Post</code> 中插入新的评论：</p>
<p><strong>附加一个相关的模型</strong></p>
<pre><code>$comment = new Comment(array('message' =&gt; 'A new comment.'));

$post = Post::find(1);

$comment = $post-&gt;comments()-&gt;save($comment);
</code></pre>
<p>在这个例子中，所插入评论的 <code>post_id</code> 字段将自动设置。</p>
<h3>相关模型 (属于)</h3>
<p>当更新一个 <code>belongsTo</code> 关系，您可以使用 <code>associate</code> 函数，这个函数将为子模型设置外键：</p>
<pre><code>$account = Account::find(10);

$user-&gt;account()-&gt;associate($account);

$user-&gt;save();
</code></pre>
<h3>插入相关模型 (多对多)</h3>
<p>当处理多对多关系时，您也可以插入相关模型。让我们继续使用我们的 <code>User</code> 和 <code>Role</code> 模型作为例子。我们能够轻松地使用 <code>attach</code> 函数为一个用户附加新的角色：</p>
<p><strong>附加多对多模型</strong></p>
<pre><code>$user = User::find(1);

$user-&gt;roles()-&gt;attach(1);
</code></pre>
<p>您也可以传递一个属性的数组，存在关系的表中：</p>
<pre><code>$user-&gt;roles()-&gt;attach(1, array('expires' =&gt; $expires));
</code></pre>
<p>当然，<code>attach</code> 的反义词是 <code>detach</code>：</p>
<pre><code>$user-&gt;roles()-&gt;detach(1);
</code></pre>
<p>您也可以使用 <code>sync</code> 函数附加相关的模型。<code>sync</code> 函数接受一个 IDs 数组。当这个操作完成，只有数组中的 IDs 将会为这个模型存在关系表中：</p>
<p><strong>使用 Sync 附加多对多关系</strong></p>
<pre><code>$user-&gt;roles()-&gt;sync(array(1, 2, 3));
</code></pre>
<p>您也可以用给定的 IDs 关联其他关系表中的值:</p>
<p><strong>同步时添加关系数据</strong></p>
<pre><code>$user-&gt;roles()-&gt;sync(array(1 =&gt; array('expires' =&gt; true)));
</code></pre>
<p>有时您可能希望创建一个新的相关的模型，并且在一行中附加它。对于此操作，您可以使用 <code>save</code> 函数：</p>
<pre><code>$role = new Role(array('name' =&gt; 'Editor'));

User::find(1)-&gt;roles()-&gt;save($role);
</code></pre>
<p>在这个例子中，新的 <code>Role</code> 模型将被保存并附加到用户模型。您也可以传递一个属性的数组加入到在这个操作中所连接的表：</p>
<pre><code>User::find(1)-&gt;roles()-&gt;save($role, array('expires' =&gt; $expires));
</code></pre>
<p><a name="touching-parent-timestamps"></a></p>
<h2>触发父模型时间戳</h2>
<p>当一个模型 <code>belongsTo</code> 另一个模型，比如一个 <code>Comment</code> 属于一个 <code>Post</code>，当更新子模型时更新父模型的时间戳通常是有用的。比如，当一个 <code>Comment</code> 模型更新，您想自动更新所属 <code>Post</code> 的 <code>updated_at</code> 时间戳。Eloquent 使之变得容易，只需要在子模型中添加 <code>touches</code> 属性包含关系的名字：</p>
<pre><code>class Comment extends Eloquent {

    protected $touches = array('post');

    public function post()
    {
        return $this-&gt;belongsTo('Post');
    }

}
</code></pre>
<p>现在，当您更新一个 <code>Comment</code>，所属的 <code>Post</code> 的 <code>updated_at</code> 字段也将被更新：</p>
<pre><code>$comment = Comment::find(1);

$comment-&gt;text = 'Edit to this comment!';

$comment-&gt;save();
</code></pre>
<p><a name="working-with-pivot-tables"></a></p>
<h2>与数据透视表工作</h2>
<p>正如您已经了解到，使用多对多关系需要一个中间表的存在。Eloquent 提供了一些非常有用与这个表交互的方式。比如，让我们假设我们的 <code>User</code> 对象有很多相关的 <code>Role</code> 对象，在访问这个关系时，我们可以在这些模型中访问数据透视表：</p>
<pre><code>$user = User::find(1);

foreach ($user-&gt;roles as $role)
{
    echo $role-&gt;pivot-&gt;created_at;
}
</code></pre>
<p>注意每一个我们检索的 <code>Role</code> 模型将自动赋值给一个 <code>pivot</code> 属性。这个属性包含一个代表中间表的模型，并且可以像其他 Eloquent 模型使用。</p>
<p>默认情况下，在 <code>pivot</code> 对象中只有键，如果您的数据透视表包含其他的属性，您必须在定义关系时指定它们：</p>
<pre><code>return $this-&gt;belongsToMany('Role')-&gt;withPivot('foo', 'bar');
</code></pre>
<p>现在，<code>foo</code> 和 <code>bar</code> 属性将可以通过 <code>Role</code> 模型的 <code>pivot</code> 对象中访问。</p>
<p>如果您想您的数据透视表有自动维护的 <code>created_at</code> 和 <code>updated_at</code> 时间戳，在关系定义时使用 <code>withTimestamps</code> 方法：</p>
<pre><code>return $this-&gt;belongsToMany('Role')-&gt;withTimestamps();
</code></pre>
<p>为一个模型在数据透视表中删除所有记录，您可以使用 <code>detach</code> 函数：</p>
<p><strong>在一个数据透视表中删除记录</strong></p>
<pre><code>User::find(1)-&gt;roles()-&gt;detach();
</code></pre>
<p>注意这个操作并不从 <code>roles</code> 删除记录，只从数据透视表中删除。</p>
<p><strong>Defining A Custom Pivot Model</strong></p>
<p>Laravel also allows you to define a custom Pivot model. To define a custom model, first create your own &quot;Base&quot; model class that extends <code>Eloquent</code>. In your other Eloquent models, extend this custom base model instead of the default <code>Eloquent</code> base. In your base model, add the following function that returns an instance of your custom Pivot model:</p>
<pre><code>public function newPivot(Model $parent, array $attributes, $table, $exists)
{
    return new YourCustomPivot($parent, $attributes, $table, $exists);
}
</code></pre>
<p><a name="collections"></a></p>
<h2>集合</h2>
<p>所有通过 <code>get</code> 方法或一个<code>relationship</code>由Eloquent返回的多结果集都是一个集合对象。这个对象实现了 <code>IteratorAggregate</code> PHP 接口，所以可以像数组一样进行遍历。然而，这个对象也有很多其他的函数来处理结果集。</p>
<p>比如，我们可以使用 <code>contains</code> 检测一个结果集是否包含指定的主键：</p>
<p><strong>检测一个集合是否包含一个键</strong></p>
<pre><code>$roles = User::find(1)-&gt;roles;

if ($roles-&gt;contains(2))
{
    //
}
</code></pre>
<p>集合也可以被转换为一个数组或JSON：</p>
<pre><code>$roles = User::find(1)-&gt;roles-&gt;toArray();

$roles = User::find(1)-&gt;roles-&gt;toJson();
</code></pre>
<p>如果一个集合被转换为一个字符转，它将以JSON格式返回：</p>
<pre><code>$roles = (string) User::find(1)-&gt;roles;
</code></pre>
<p>Eloquent 集合也包含一些方法来遍历和过滤所包含的项：</p>
<p><strong>遍历集合</strong></p>
<pre><code>$roles = $user-&gt;roles-&gt;each(function($role)
{
    //
});
</code></pre>
<p><strong>过滤集合</strong></p>
<p>过滤集合时，你所提供的回调函数将被作为 <a href="http://php.net/manual/en/function.array-filter.php" target="_blank">array_filter</a> 的回调函数使用。</p>
<pre><code>$users = $users-&gt;filter(function($user)
{
    if($user-&gt;isAdmin())
    {
        return $user;
    }
});
</code></pre>
<blockquote>
<p><strong>注意：</strong> 当过滤集合并转化为JSON格式时，应首先调用 <code>values</code> 函数重置数组内所有的键（key）。</p>
</blockquote>
<p><strong>对每个集合项应用回调函数</strong></p>
<pre><code>$roles = User::find(1)-&gt;roles;

$roles-&gt;each(function($role)
{
    //  
});
</code></pre>
<p><strong>根据一个值排序集合</strong></p>
<pre><code>$roles = $roles-&gt;sortBy(function($role)
{
    return $role-&gt;created_at;
});
</code></pre>
<p>有时，您可能希望返回一个自定义的集合以及自己添加的函数。您可以通过在 Eloquent 模型中重写 <code>newCollection</code> 函数指定这些：</p>
<p><strong>返回一个自定义集合类型</strong></p>
<pre><code>class User extends Eloquent {

    public function newCollection(array $models = array())
    {
        return new CustomCollection($models);
    }

}
</code></pre>
<p><a name="accessors-and-mutators"></a></p>
<h2>访问器和调整器</h2>
<p>Eloquent 为获取和设置模型的属性提供了一种便利的方式。简单的在模型中定义一个 <code>getFooAttribute</code> 函数声明一个访问器。记住，这个函数应该遵循 &quot;camel-casing&quot; 拼写格式，即使您的数据库使用 &quot;snake-case&quot;：</p>
<p><strong>定义一个访问器</strong></p>
<pre><code>class User extends Eloquent {

    public function getFirstNameAttribute($value)
    {
        return ucfirst($value);
    }

}
</code></pre>
<p>在上面的例子中，<code>first_name</code> 字段有一个访问器。注意属性的值被传递到访问器。</p>
<p>调整器以类似的方式声明：</p>
<p><strong>定义一个调整器</strong></p>
<pre><code>class User extends Eloquent {

    public function setFirstNameAttribute($value)
    {
        $this-&gt;attributes['first_name'] = strtolower($value);
    }

}
</code></pre>
<p><a name="date-mutators"></a></p>
<h2>日期调整器</h2>
<p>默认情况下，Eloquent 将转换 <code>created_at</code>、<code>updated_at</code> 以及 <code>deleted_at</code> 字段为 <a href="https://github.com/briannesbitt/Carbon" target="_blank">Carbon</a> 的实例，它提供了各种有用的函数，并且继承自原生 PHP 的 <code>DateTime</code> 类。</p>
<p>您可以指定哪些字段自动调整，设置禁用调整，通过在模型中重写 <code>getDates</code> 函数：</p>
<pre><code>public function getDates()
{
    return array('created_at');
}
</code></pre>
<p>当一个字段被认为是一个日期，您可以设置它的值为一个 UNIX 时间戳，日期字符串 (<code>Y-m-d</code>)，日期时间字符串，当然也可以是一个 <code>DateTime</code> 或 <code>Carbon</code> 实例。</p>
<p>完全禁用日期调整，从 <code>getDates</code> 函数中返回一个空数组：</p>
<pre><code>public function getDates()
{
    return array();
}
</code></pre>
<p><a name="model-events"></a></p>
<h2>模型事件</h2>
<p>Eloquent 模型触发一些事件，允许您使用以下函数在模型的生命周期内的许多地方插入钩子：<code>creating</code>、<code>created</code>、<code>updating</code>、 <code>updated</code>、<code>saving</code>、<code>saved</code>、<code>deleting</code>、<code>deleted</code> 、<code>restoring</code>、<code>restored</code>。</p>
<p>每当一个新的项目第一次被保存，<code>creating</code> 和 <code>created</code> 事件将被触发。如果一个项目不是新的并且 <code>save</code> 函数被调用， <code>updating</code>/<code>updated</code> 事件将被触发。在这两种情况下，<code>saving</code>/<code>saved</code> 事件都将被触发。</p>
<p>如果从 <code>creating</code>, <code>updating</code> 或者 <code>saving</code> 返回 <code>false</code> ，该操作将被取消：</p>
<p><strong>通过事件取消保存操作</strong></p>
<pre><code>User::creating(function($user)
{
    if ( ! $user-&gt;isValid()) return false;
});
</code></pre>
<p>Eloquent 模型也包含一个静态的 <code>boot</code> 函数，它可以提供一个方便的地方注册事件绑定。</p>
<p><strong>设置一个模型 Boot 函数</strong></p>
<pre><code>class User extends Eloquent {

    public static function boot()
    {
        parent::boot();

        // Setup event bindings...
    }

}
</code></pre>
<p><a name="model-observers"></a></p>
<h2>模型观察者</h2>
<p>为加强处理模型事件，您可以注册一个模型观察者。一个观察者类可以包含很多函数对应于很多模型事件。比如，<code>creating</code>, <code>updating</code>, <code>saving</code> 函数可以在一个观察者中，除其他模型事件名之外。</p>
<p>因此，比如，一个模型观察者可以像这样：</p>
<pre><code>class UserObserver {

    public function saving($model)
    {
        //
    }

    public function saved($model)
    {
        //
    }

}
</code></pre>
<p>您可以使用 <code>observe</code> 函数注册一个观察者实例：</p>
<pre><code>User::observe(new UserObserver);
</code></pre>
<p><a name="converting-to-arrays-or-json"></a></p>
<h2>转为数组或JSON</h2>
<p>当构建JSON APIs，您可能经常需要转换您的模型和关系为数组或JSON字符串。所以，Eloquent 包含这些方法。转换一个模型和它加载的关系为一个数组，您可以使用 <code>toArray</code> 函数：</p>
<p><strong>转换一个模型为数组</strong></p>
<pre><code>$user = User::with('roles')-&gt;first();

return $user-&gt;toArray();
</code></pre>
<p>注意模型的全部集合也可以被转为数组：</p>
<pre><code>return User::all()-&gt;toArray();
</code></pre>
<p>转换一个模型为JSON字符串，您可以使用 <code>toJson</code> 函数：</p>
<p><strong>转换一个模型为JSON字符串</strong></p>
<pre><code>return User::find(1)-&gt;toJson();
</code></pre>
<p>注意当一个模型或集合转换为一个字符串，它将转换为JSON，这意味着您可以直接从应用程序的路由中返回 Eloquent 对象！</p>
<p><strong>从路由中返回一个模型</strong></p>
<pre><code>Route::get('users', function()
{
    return User::all();
});
</code></pre>
<p>有时您可能希望限制包含在模型数组或JSON中的属性，比如密码，为此，在模型中添加一个隐藏属性：</p>
<p><strong>从数组或JSON转换中隐藏属性</strong></p>
<pre><code>class User extends Eloquent {

    protected $hidden = array('password');

}
</code></pre>
<blockquote>
<p><strong>注意：</strong> 如果关系被隐藏了，请使用关系的 <strong>method</strong> 名称，而不是动态的访问名称。</p>
</blockquote>
<p>或者，您可以使用 <code>visible</code> 属性定义一个白名单：</p>
<pre><code>protected $visible = array('first_name', 'last_name');
</code></pre>
<p><a name="array-appends"></a>
某些时候，你可能需要向数据库添加一组属性，而这组属性并在数据库中没有对应的字段。为了能够实现这一需求，可以简单的为每个属性定义一个访问器：</p>
<pre><code>public function getIsAdminAttribute()
{
    return $this-&gt;attributes['admin'] == 'yes';
}
</code></pre>
<p>一旦创建了访问器，只需将属性添加到模型的<code>appends</code>属性中：</p>
<pre><code>protected $appends = array('is_admin');
</code></pre>
<p>一旦将属性添加到<code>appends</code>列表中，它就将被包含在模型和JSON表单中。</p>

		</article>
	</div>


	<footer class="main">
		<ul>
			<li class="nav-docs"><a href="../index.html">中文文档</a></li>
			<li class="nav-community"><a href="http://wenda.golaravel.com" target="_blank">问答社区</a></li>
			<li class="nav-api"><a href="http://laravel.com/api/5.0/" target="_blank">API</a></li>
			<li class="nav-laracasts"><a href="https://laracasts.com" target="_blank">视频教程（国外）</a></li>
			<li class="nav-forge"><a href="https://forge.laravel.com" target="_blank">Forge</a></li>
			
		</ul>
		<p>Laravel is a trademark of Taylor Otwell. Copyright &copy; Taylor Otwell.</p>
		<p class="less-significant"><a href="http://jackmcdade.com" target="_blank">Design by Jack McDade</a></p>
	</footer>

	<script src="../../assets/js/laravel.js"></script>
	<script src="../../assets/js/viewport-units-buggyfill.js"></script>
	<script>window.viewportUnitsBuggyfill.init();</script>
	<script type="text/javascript">
	var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");
	document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3Fc8d13872a523d9c286aa7affbe0921f1' type='text/javascript'%3E%3C/script%3E"));
	</script>
</body>
</html>
